import json
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.font_manager import FontProperties

# 解决matplotlib中文显示问题
# 请确保您的系统中有支持中文的字体，例如 'SimHei' 或 'Microsoft YaHei'
# 如果没有，可以下载一个中文字体文件（.ttf），并修改下面的路径
try:
    font = FontProperties(fname='C:/Windows/Fonts/simhei.ttf', size=12) # Windows系统常见路径
except IOError:
    try:
        font = FontProperties(fname='/System/Library/Fonts/STHeiti Light.ttc', size=12) # MacOS系统常见路径
    except IOError:
        print("未找到中文字体，图例和标题可能显示为方框。")
        font = FontProperties(size=12) # 使用默认字体


def plot_performance_curve(file_path, reallocation_threshold=0.25):
    """
    解析jsonl文件，处理资金调拨，并绘制净值曲线图。

    Args:
        file_path (str): jsonl文件的路径。
        reallocation_threshold (float): 判断为资金调拨的阈值。
    """
    records = []
    with open(file_path, 'r', encoding='utf-8') as f:
        for line in f:
            try:
                records.append(json.loads(line))
            except json.JSONDecodeError:
                continue

    # 展开JSON数据，并使用 'meta_' 前缀解决字段名冲突
    df_capital = pd.json_normalize(
        records,
        'sub_account_capital_list',
        ['update_time', 'total_capital'],
        meta_prefix='meta_'
    )

    # 【代码修复】: 在透视操作前，将所有资金相关的列转换为数字类型
    # 这是解决 'TypeError: Could not convert string to numeric' 的关键
    df_capital['capital'] = pd.to_numeric(df_capital['capital'], errors='coerce')
    df_capital['meta_total_capital'] = pd.to_numeric(df_capital['meta_total_capital'], errors='coerce')

    # 删除可能因转换失败产生的空值行
    df_capital.dropna(subset=['capital', 'meta_total_capital'], inplace=True)

    # 使用顶层的时间戳作为主时间索引，创建数据透视表
    df_pivot = df_capital.pivot_table(
        index='meta_update_time',
        columns='name',
        values='capital'
    ) # 注意这里已经不需要 .astype(float) 了，因为上面已经转换过了

    # 将总资金数据合并进来
    df_total = df_capital[['meta_update_time', 'meta_total_capital']].drop_duplicates().set_index('meta_update_time')
    df_total = df_total.rename(columns={'meta_total_capital': 'total_capital'})
    df_pivot = pd.concat([df_pivot, df_total], axis=1)

    # 将时间戳索引转换为datetime对象，并排序
    df_pivot.index = pd.to_datetime(df_pivot.index, unit='ms')
    df_pivot.index.name = 'update_time'
    df_pivot = df_pivot.sort_index()

    # ---- 核心逻辑：处理资金调拨并计算净值 (这部分无需修改) ----
    df_performance = df_pivot.copy()
    pct_change = df_performance.pct_change()

    for col in df_performance.columns:
        if col == 'total_capital':
            continue

        reallocation_points = pct_change[abs(pct_change[col] - pct_change['total_capital']) > reallocation_threshold].index

        for point in reallocation_points:
            prev_point_loc = df_performance.index.get_loc(point) - 1
            if prev_point_loc < 0:
                continue
            prev_index = df_performance.index[prev_point_loc]

            true_growth = 1 + pct_change.loc[point, 'total_capital']
            adjusted_prev_capital = df_performance.loc[point, col] / true_growth

            original_prev_capital = df_performance.loc[prev_index, col]
            # 避免除以零的错误
            if original_prev_capital == 0:
                continue
            factor = adjusted_prev_capital / original_prev_capital

            df_performance.loc[:prev_index, col] *= factor

    # ---- 将调整后的资金曲线转换为净值曲线 (这部分无需修改) ----
    df_net_value = df_performance / df_performance.iloc[0]

    # ---- 绘图 (这部分无需修改) ----
    fig, ax = plt.subplots(figsize=(15, 8))

    for column in df_net_value.columns:
        if column == 'total_capital':
            ax.plot(df_net_value.index, df_net_value[column], label='总资金净值', linestyle='--', color='red', linewidth=2)
        else:
            ax.plot(df_net_value.index, df_net_value[column], label=column)

    ax.set_title("资金净值曲线 (已处理资金调拨)", fontproperties=font)
    ax.set_xlabel("更新时间", fontproperties=font)
    ax.set_ylabel("净值 (初始为1)", fontproperties=font)
    ax.legend(prop=font)
    ax.grid(True)

    fig.autofmt_xdate()
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M'))

    plt.show()


if __name__ == '__main__':
    # 将 "your_file.jsonl" 替换为您的jsonl文件名
    plot_performance_curve("master_account_capital_2025-09.jsonl")